#!/usr/bin/env python3
# -*- coding: utf-8 -*-

from fastapi import FastAPI
from fastapi.responses import ORJSONResponse
from fastapi.middleware import Middleware
from fastapi.middleware.cors import CORSMiddleware
from fastapi_limiter import FastAPILimiter
from contextlib import asynccontextmanager
from tortoise import Tortoise
from aerich import Command
from typing import Dict
import os

from app import api_v1_router
from utils import (
    instance_thread_pool
)
from common.log import init_log, log
from common.redis import redis_client
from common.exception.exception_handlers import register_exception
from middleware .access_middleware import AccessMiddleware
from settings.config import settings
from utils.health_check import http_limit_callback

from app.admin import init_superuser

def register_middleware(app: FastAPI) -> None:
    # 跨域
    if settings.MIDDLEWARE_CORS:
        app.add_middleware(
            CORSMiddleware,
            allow_origins=settings.CORS_ORIGINS,
            allow_credentials=settings.CORS_ALLOW_CREDENTIALS,
            allow_methods=settings.CORS_ALLOW_METHODS,
            allow_headers=settings.CORS_ALLOW_HEADERS,
        )
    # 接口访问日志
    if settings.MIDDLEWARE_ACCESS:
        app.add_middleware(AccessMiddleware)


def register_db(app: FastAPI):
    if settings.ENABLE_DB:
        if settings.DB_TYPE == 'sqlite':
            if not os.path.exists(settings.DB_PATH):
                os.makedirs(
                    os.path.abspath(settings.DB_PATH), 
                    exist_ok=True
                )


def register_routers(app: FastAPI, prefix: str = "/api"):
    app.include_router(api_v1_router, prefix=prefix)
    
async def init_system():
    await init_superuser()
    

@asynccontextmanager
async def lifespan(app: FastAPI):
    if settings.FORMAT_LOG:
        await init_log()
    log.debug("程序启动成功")
    if settings.ENABLE_DB:
        db_config: Dict = settings.TORTOISE_ORM
        await Tortoise.init(config=db_config)
        # 初始化 aerich
        command = Command(tortoise_config=db_config, app="models")
        await command.init()
        if os.getenv('ENV') == 'dev':
            await Tortoise.generate_schemas(safe=True)
    if settings.ENABLE_REDIS:
        '''如果 ENABLE_REDIS true 初始化 redis'''
        await redis_client.init_redis()
    if settings.ENABLE_LIMITER and settings.ENABLE_REDIS:
        '''启用 limiter，初始化 limiter'''
        await FastAPILimiter.init(
            redis=redis_client, prefix=settings.REQUEST_LIMITER_REDIS_PREFIX, http_callback=http_limit_callback
        )
    await init_system()
    log.debug(f"环境：{settings.ENV}")
    yield
    # 关闭数据库
    if settings.ENABLE_DB:
        await Tortoise.close_connections()
    await instance_thread_pool.shutdown()
    if settings.ENABLE_LIMITER and settings.ENABLE_REDIS:
        '''关闭 limiter'''
        await FastAPILimiter.close()
    if settings.ENABLE_REDIS:
        '''关闭 redis'''
        await redis_client.close()
    log.debug("程序关闭")
    
    
def create_app(lifespan) -> FastAPI:
    app = FastAPI(
        title=settings.APP_TITLE,
        description=settings.APP_DESCRIPTION,
        version=settings.VERSION,
        docs_url=settings.DOCS_URL,
        redoc_url=settings.REDOCS_URL,
        openapi_url=settings.OPENAPI_URL,
        lifespan=lifespan,
        default_response_class=ORJSONResponse
    )
    register_exception(app)
    register_routers(app, prefix="/api")
    register_middleware(app)
    register_db(app)
    return app

